<template>
  <div class='inkling-device'>
    <j-spin :spinning='spinning'>
      <div class='search-box'>
        <div class='search-warp'>
          <j-advanced-search
            v-if='!spinning'
            :columns='columns'
            type='simple'
            @search='handleSearch'
            class='device-inkling'
            target='device-inkling'
          />
        </div>
        <div class='multiple' v-if='multiple'>
          <j-checkbox @change='checkChange'>全选</j-checkbox>
        </div>
      </div>
      <div class='device-list-warp'>
        <j-scrollbar v-if='deviceList.length'>
          <j-spin :spinning='deviceSpinning'>
            <div class='device-list-items'>
              <div
                v-for='item in deviceList'
                :class='{
                  "device-list-item": true,
                  "active": checkKeys.includes(item.id),
                  "disabled": disabledKeys.includes(item.id)
                }'
                @click='() => deviceClick(item.id, item)'
              >
                <template v-if='disabledKeys.includes(item.id)'>
                  <j-tooltip
                    title='该设备已绑定平台设备'
                  >
                      <span class='item-title'>{{ item.id }}</span>
                  </j-tooltip>
                </template>
                <span v-else class='item-title'>
                  {{ item.id }}
                </span>
                <a-icon
                  v-if='checkKeys.includes(item.id)'
                  type='CheckOutlined'
                />
              </div>
            </div>
          </j-spin>
        </j-scrollbar>
        <j-empty
          v-else
          description='暂无数据'
          style='padding-top: 24px'
        />
        <div class='device-list-pagination'>
          <j-pagination
            v-if='showPage'
            :total='pageData.total'
            :current='pageData.pageIndex + 1'
            :pageSize='pageData.pageSize'
            :show-total='() => {
              const minSize = pageData.pageIndex *  pageData.pageSize + 1;
              const MaxSize = (pageData.pageIndex + 1) * pageData.pageSize;
              return `第 ${minSize} - ${MaxSize > pageData.total ? pageData.total : MaxSize } 条/总共 ${pageData.total} 条`;
            }'
            @change='pageChange'
          />
        </div>
      </div>
    </j-spin>
  </div>
</template>

<script setup lang='ts' name='InklingDevice'>

import { getCommandsByAccess, getCommandsDevicesByAccessId } from '@/api/link/accessConfig'
import { getInkingDevices } from '@/api/device/instance'
import { isArray } from 'lodash-es'

type Emit = {
  (e: 'update:value', data: string | string[]): void
  (e: 'change', data: any | any[]): void
}
const props = defineProps({
  value: {
    type: [String, Array],
    default: undefined
  },
  accessId: {
    type: String,
    default: undefined
  },
  multiple: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits<Emit>()

const spinning = ref(true)
const deviceSpinning = ref(false)
const deviceList = ref([])
const disabledKeys = ref<string[]>([])
const checkKeys = ref<string[]>([])
const checkCache = ref<Map<string, any>>(new Map())
const showPage = ref(false)
const pageData = reactive({
  pageSize: 10,
  pageIndex: 0,
  total: 0
})
const params = ref({
  terms: []
})

const columns = ref([])

const queryInkingDevices = (data: string[]) => {
  return new Promise(async (resolve) => {
    if (!data.length) {
      resolve(true)
      return
    }

    const res = await getInkingDevices(data)
    if (res) {
      disabledKeys.value = res.result?.map(item => item.externalId)
    }
    resolve(true)
  })
}

const getDeviceList = async () => {
  const resp = await getCommandsDevicesByAccessId(props.accessId!, {
    pageIndex: pageData.pageIndex,
    pageSize: pageData.pageSize,
    terms: params.value.terms
  }).catch(() => ({ success: false }))
  if (resp.success) {
    await queryInkingDevices(resp.result?.data.map(item => item.id) || [])
    deviceList.value = resp.result?.data || []
    pageData.total = resp.result?.total || 0
  }
}

const checkChange = (e: any) => { // 全选
  if (e.target.checked) {
    const keys = deviceList.value.filter(item => {
      //  过滤已选中和已绑定
      const type = !checkKeys.value.includes(item.id) && !disabledKeys.value.includes(item.id)
      if (type && checkCache.value.has(item.id)) {
        checkCache.value.set(item.id, item)
      }
      return type
    }).map(item => item.id)
    checkKeys.value = [...checkKeys.value, ...keys]
    emit('update:value', checkKeys.value)
    emit('change', [...checkCache.value.values()])
  } else {
    checkCache.value.clear()
    checkKeys.value = []
    emit('update:value', [])
    emit('change', [])
  }
}

const handleSearch = (p: any) => { // 查询
  pageData.pageIndex = 0
  params.value = p
  getDeviceList()
}

const pageChange = (page: number, pageSize: number) => { // 分页变化
  pageData.pageSize = pageSize
  pageData.pageIndex = page - 1
  getDeviceList()
}

const init = async () => {
  if (props.accessId) {
    const resp = await getCommandsByAccess(props.accessId)
    if (resp.success) {
      const item = resp.result?.[0]
      if (item) {
        showPage.value = item.id === 'QueryDevicePage' // 分页
        columns.value = item.expands?.terms?.map(t => ({
          title: t.name,
          dataIndex: t.id,
          search: {
            type: t.valueType.type
          }
        }))
      }
    }
    spinning.value = false
    await getDeviceList()
  }
}

const deviceClick = (id: string, option: any) => {
  if (option.disabled || disabledKeys.value.includes(id)) return

  const _check = new Set(checkKeys.value)

  if (props.multiple) { // 多选
    if (_check.has(id)) {
      _check.delete(id)
      checkCache.value.delete(id)
    } else {
      checkCache.value.set(id, option)
      _check.add(id)
    }
    checkKeys.value = [..._check.values()]
    emit('update:value', checkKeys.value)
    emit('change', [...checkCache.value.values()])
  } else {
    checkKeys.value = [id]
    emit('update:value', id)
    emit('change', option)
  }
}

watch(() => props.value, (newValue) => {
  if (!newValue) {
    checkKeys.value = []
    return
  }
  if (isArray(newValue)) {
    checkKeys.value = newValue
  } else {
    checkKeys.value = [newValue as string]
  }
}, { immediate: true, deep: true })

onMounted(() => {
  init()
})

</script>

<style scoped lang='less'>
.inkling-device {
  min-height: 200px;
}

.search-box {
  padding-bottom: 24px;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  margin-bottom: 12px;
  gap: 24px;
  align-items: center;

  :deep(.device-inkling) {
    padding: 0;
    margin: 0;
    padding-bottom: 0;
  }

  .search-warp {
    flex: 1 1 auto;
  }

  .multiple {
    width: 60px;
  }
}


.device-list-warp {
  .device-list-items {
    .device-list-item {
      padding: 10px 16px;
      color: #4F4F4F;
      border-bottom: 1px solid #f0f0f0;
      display: flex;
      justify-content: space-between;

      > .item-title {
        flex: 1 1 auto;
      }

      &:hover {
        background-color: rgba(47, 84, 235, 0.06);
      }

      &.active {
        background-color: rgba(153, 153, 153, 0.06);
        color: @primary-color;
      }

      &.disabled {
        cursor: not-allowed;
        background-color: rgba(153, 153, 153, 0.06);
      }
    }
  }

  .device-list-pagination {
    margin-top: 24px;
    text-align: right;
  }
}
</style>